//
//  ADActionSheet.swift
//  ADKit
//
//  Created by Adoma on 2020/10/26.
//

import UIKit
import SnapKit
import RxSwift
import RxCocoa

extension ADActionSheet {
    struct Layout {
        static let kMinTitleHeight: CGFloat = 40
        static let kContentViewMargin: CGFloat = 20
        static let kViewMargin: CGFloat = 23
        static let kButtonHeight: CGFloat = 51
    }
    struct Font {
        static let kTitleFont = UIFont.pingfang(with: 13)
        static let kButtonTextFont = UIFont.pingfang(with: 15)
    }
    struct Color {
        static let kSeparatorColor = ADKit.Color.kEEEEEE
        static let kTitleColor = ADKit.Color.k666666
        static let kMarginColor = ADKit.Color.kF6F6F6
        
    }
    public enum Style {
        case `default`
        case onlySure
    }
}

public class ADAction {
    
    public enum Style {
        
        case `default`
        case destructive
        case cancel
        case other(color: UIColor)
        
        var color: UIColor {
            switch self {
            case .destructive:
                ADKit.Color.kE64A46
            case .cancel:
                ADKit.Color.k333333
            case .other(let color):
                color
            default:
                ADKit.Color.k002FA7
            }
        }
    }
    
    var title: String
    var style: Style

    public typealias Action = ()->Void
    var action: Action?
    public init(title: String, style: Style = .default, action: Action? = nil) {
        self.title = title
        self.style = style
        self.action = action
    }
}

public class ADActionSheet: UIView {
    
    public var title: String?
    public var attrTitle: NSAttributedString?
    
    public var cancelTitle = "取消"
    public var cancelCallback: ADAction.Action?
    
    var bag = DisposeBag()
    var actions: [ADAction] = []
    let contentView = UIView()
    var contentTopConstraint: Constraint!
    var contentBottomConstraint: Constraint!
    
    public init() {
        super.init(frame: UIScreen.main.bounds)
        
        backgroundColor = .clear
        
        contentView.backgroundColor = .white
        contentView.layer.shadowOffset = .init(width: 0, height: -3)
        contentView.layer.cornerRadius = 8
        contentView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
        contentView.layer.masksToBounds = true
        addSubview(contentView)
        contentView.snp.makeConstraints { (make) in
            self.contentTopConstraint = make.top.equalTo(self.snp.bottom).priority(.high).constraint
            make.left.right.equalToSuperview()
            self.contentBottomConstraint = make.bottom.equalToSuperview().priority(.low).constraint
        }
    }
    
    func prepareSubViews(parent: UIView) {
        
        var last: UIView = contentView
        
        let hasTitle = self.title != nil || self.attrTitle != nil
        if hasTitle {
            
            let titleContent = UIView().then {
                contentView.addSubview($0)
                $0.snp.makeConstraints { (make) in
                    make.top.left.right.equalToSuperview()
                    make.height.greaterThanOrEqualTo(Layout.kMinTitleHeight)
                }
            }
            
            let titleLabel = UILabel().then {
                $0.font = Font.kTitleFont
                $0.textColor = Color.kTitleColor
                $0.textAlignment = .center
                $0.numberOfLines = 0
                titleContent.addSubview($0)
                $0.snp.makeConstraints { (make) in
                    make.top.bottom.equalToSuperview().inset(20)
                    make.left.right.equalToSuperview().inset(Layout.kViewMargin)
                }
            }
            
            if let attr = attrTitle {
                titleLabel.attributedText = attr
            } else {
                titleLabel.text = title
            }
            
            last = titleContent
        }
        
        for action in actions.enumerated() {
            
            let sep = UIView().then {
                contentView.addSubview($0)
                $0.backgroundColor = Color.kSeparatorColor
                $0.snp.makeConstraints { (make) in
                    make.left.right.equalToSuperview()
                    if hasTitle == false && action.offset == 0 {
                        make.top.equalTo(last)
                        make.height.equalTo(0)
                    } else {
                        make.top.equalTo(last.snp.bottom)
                        make.height.equalTo(kSeparatorLineH)
                    }
                }
            }
            
            let actButton = UIButton(title: action.element.title, font: Font.kButtonTextFont, color: action.element.style.color).then {
                contentView.addSubview($0)
                $0.titleLabel?.numberOfLines = 0
                $0.titleLabel?.textAlignment = .center
                $0.snp.makeConstraints { (make) in
                    make.left.right.equalToSuperview()
                    make.top.equalTo(sep.snp.bottom)
                    make.height.equalTo(Layout.kButtonHeight)
                }
            }
            
            actButton.rx.tap.subscribe(onNext: { [weak self] in
                action.element.action?()
                self?.hidden()
            }).disposed(by: bag)
            
            last = actButton
        }
        
        let hasActions = actions.count > 0
        if hasActions  {
            last = UIView().then {
                contentView.addSubview($0)
                $0.backgroundColor = Color.kMarginColor
                $0.snp.makeConstraints { (make) in
                    make.left.right.equalToSuperview()
                    make.top.equalTo(last.snp.bottom)
                    make.height.equalTo(8)
                }
            }
        }
        
        let cancelContent = UIView().then {
            self.contentView.addSubview($0)
            $0.backgroundColor = .white
            $0.snp.makeConstraints { (make) in
                make.left.right.equalToSuperview()
                if hasTitle || hasActions {
                    make.top.equalTo(last.snp.bottom)
                } else {
                    make.top.equalTo(last)
                }
                make.bottom.equalToSuperview()
            }
        }
        
        let cancel = UIButton(title: cancelTitle, font: Font.kButtonTextFont, color: ADAction.Style.cancel.color).then {
            cancelContent.addSubview($0)
            $0.snp.makeConstraints { (make) in
                make.top.left.right.equalToSuperview()
                make.bottom.equalToSuperview().inset(kSafeAreaBottom)
                make.height.equalTo(Layout.kButtonHeight)
            }
        }
        
        cancel.rx.tap
            .throttle(.seconds(1), scheduler: MainScheduler.instance)
            .subscribe (onNext: { [weak self] in
            self?.cancelCallback?()
            self?.hidden()
        }).disposed(by: bag)
        
        parent.addSubview(self)
        layoutIfNeeded()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    public func add(action: ADAction) {
        actions.append(action)
    }
    
    public func show(in view: UIView? = WindowManager.keyWindow) {
        
        if Thread.current != .main {
            DispatchQueue.main.async {
                self.show(in: view)
            }
            return
        }
        
        guard let parent = view else {
            return
        }
        
        parent.endEditing(false)
        
        prepareSubViews(parent: parent)
        
        self.contentTopConstraint.update(priority: .low)
        self.contentBottomConstraint.update(priority: .high)
        
        UIView.animate(withDuration: 0.25, delay: 0, options: [.curveEaseOut]) {
            self.backgroundColor = UIColor.black.alpha(0.5)
            self.layoutIfNeeded()
        } completion: { (_) in
            
        }
        
    }
    
    public func hidden() {
        
        self.contentTopConstraint.update(priority: .high)
        self.contentBottomConstraint.update(priority: .low)
        
        UIView.animate(withDuration: 0.2) {
            self.layoutIfNeeded()
        } completion: { (_) in
            self.removeFromSuperview()
        }
        
    }
    
    deinit {
        ADLogger(adkit: Self.self)
            .debug(#function)
    }
}
